#include "map.h"

Map::Map(const char *MapName)
{
	setMapFile( MapName );
}

Map::Map( Map &map )
{
	for( unsigned int i = 0; i < map.getMapTileImageNames().size(); i++ )
	{
		this->mapTileImageNames.push_back( map.getMapTileImageNames().at( i ) );
	}

	this->map = new Tile*[MAX_MAP_SIZE];
	for( int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		this->map[i] = new Tile[MAX_MAP_SIZE];
	}

	for( int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		for( int j = 0; j < MAX_MAP_SIZE; j++ )
		{
			this->getMapTiles()[i][j] = map.map[i][j];
		}
	}
}

Map::~Map()
{
	for( int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		delete [] this->map[i];
	}
}

void Map::setMapFile( const char *MapName )
{
	MapFileReader mapFile( MapName );
	 
	if( !collisionBoxImage.LoadFromFile( "collisionBoarder.png" ) )
	{
		exit(1);
	}
	this->collisionBoxSprite.SetImage( collisionBoxImage );
	// initualizes the collision array and the map array
	
	this->map = new Tile*[MAX_MAP_SIZE];
	for( int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		this->map[i] = new Tile[MAX_MAP_SIZE];
	}

	//this->mapTileImageNames = mapFile.getTileImageNamesVector;
	// sets the properties of each tile from the map file
	for( int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		for( int j = 0; j < MAX_MAP_SIZE; j++ )
		{
			map[i][j].setCollision( doesCollide( mapFile.getMapArray()[i][j] ) );
			map[i][j].setNumber( getNumber( mapFile.getMapArray()[i][j] ) );
			map[i][j].setImageName( mapFile.getTileImageNamesVector()[map[i][j].getNumber()] );
			std::string temp;
			temp += TILE_FOLDER;
			temp += "//";
			temp += mapFile.getTileImageNamesVector()[map[i][j].getNumber()];
			map[i][j].setImageNameAndLocation( temp );
			map[i][j].setHex( mapFile.getMapArray()[i][j] );
			map[i][j].setBin( HexConverter( mapFile.getMapArray()[i][j] ) );
			map[i][j].setRect( (float)i * TILE_SIZE, (float)(i * TILE_SIZE) + TILE_SIZE, (float)j * TILE_SIZE, (float)( j * TILE_SIZE ) + TILE_SIZE ); 
		}
	}
	for( unsigned int i = 0; i < mapFile.getTileImageNamesVector().size(); i++ )
	{
		this->mapTileImageNames.push_back( mapFile.getTileImageNamesVector()[i].c_str() );
	}
}

//returns true if image was added and false if it was not
unsigned int Map::push_backMapTileImageName( std::string image )
{
	unsigned int i = 0;
	for(; i < this->mapTileImageNames.size(); i++ )
	{
		if( this->mapTileImageNames[i].compare( image ) == 0 )
		{
			return i;
		}
	}
	this->mapTileImageNames.push_back( image );
	return i;
}

std::vector<std::string> Map::getMapTileImageNames()
{
	return this->mapTileImageNames;
}

Tile **Map::getMapTiles()
{
	return this->map;
}

void Map::Save( const char *mapFileOut )
{
	std::ofstream outFile( mapFileOut );
	for( unsigned int i = 0; i < this->mapTileImageNames.size(); i++ )
	{
		outFile.write( this->mapTileImageNames[i].c_str(), (std::streamsize)this->mapTileImageNames[i].size() );
		if( i != MAX_MAP_SIZE - 1 )
		{
			outFile.write(" ", SINGLE_CHAR_LENGTH );
		}
	}
	outFile.write( "\n", SINGLE_CHAR_LENGTH );
	for( unsigned int i = 0; i < MAX_MAP_SIZE; i++ )
	{
		for( unsigned int j = 0; j < MAX_MAP_SIZE; j++ )
		{
			outFile.write( this->map[i][j].getHex().c_str(), TILE_HEX_VALUE_SIZE );
			if( j != MAX_MAP_SIZE - 1 )
			{
				outFile.write( " ", SINGLE_CHAR_LENGTH );
			}
		}
		if( i != MAX_MAP_SIZE - 1 )
		{
			outFile.write( "\n", SINGLE_CHAR_LENGTH );
		}
	}
	outFile.close();
}

bool doesCollide( std::string &hexString )
{
	std::string tempBinNumber = HexConverter( hexString );
	if( tempBinNumber.at( COLLISION_BIT ) == '1' )
	{
		return true;
	}
	else 
	{
		return false;
	}
}
unsigned int getNumber( std::string &hexString )
{
	unsigned int number = 0;
	std::string tempBinNumber = HexConverter( hexString );
	for( unsigned int i = 7; i > 0; i-- )
	{
		if( tempBinNumber.at( i ) == '1' )
		{
			number += (unsigned int)pow( 2.f, (int)abs( (int)(i - 7) ) );
		}
	}
	return number;
}


void Map::draw( sf::RenderWindow & app, bool showCollision )
{
	int width = 0, height = 0;
	for( int i = 0; i < MAP_DRAW_HEIGHT; i++ )
	{
		for( int j = 0; j < MAP_DRAW_WIDTH; j++ )
		{
			this->map[i][j].getSprite().SetX( (float)width );
			this->map[i][j].getSprite().SetY( (float)height );
			app.Draw( this->map[i][j].getSprite() );

			if( this->map[i][j].getCollision() && showCollision )
			{
				collisionBoxSprite.SetPosition( (float)width, (float)height );
				app.Draw( collisionBoxSprite );
			}
			width += TILE_SIZE;
		}
		height += TILE_SIZE;
		width = 0;
	}
}